package ee.ut.cs.mc.madp.p2pdivider.networking;

import static ee.ut.cs.mc.madp.p2pdivider.BaseDividerActivity.HANDLER_TOAST;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.HashSet;
import java.util.Set;

import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;

import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import ee.ut.cs.mc.madp.p2pdivider.BaseDividerActivity;
import ee.ut.cs.mc.madp.p2pdivider.Command;
import ee.ut.cs.mc.madp.p2pdivider.Utils;

/**
 * @author Kaarel Jõgeva
 *
 */
public class DividerClient extends WebSocketClient {

    public static final String TAG = DividerClient.class.getCanonicalName();

    private InetAddress newHost = null;
    private final Handler handler;
    private Context context = null;
    private String filename = null;

    public DividerClient(Handler handler, URI serverURI) {
        super(serverURI);
        this.handler = handler;
    }

    public DividerClient(Handler handler, Context context, URI serverURI) {
        this(handler, serverURI);
        this.context = context;
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {
        String stuff = "Opened clientside: " + handshakedata.getHttpStatus();
        Log.i(TAG, stuff);
        Message.obtain(handler, HANDLER_TOAST, stuff).sendToTarget();
    }

    @Override
    public void onMessage(String message) {
        String stuff = "Received message! " + message;
        Log.i(TAG, stuff);

        int index = -1;

        if ((index = message.indexOf(BaseDividerActivity.OP_SEPARATOR)) > -1) {
            String op = message.substring(0, index);
            String data = message.substring(index + 1);
            try {
                handleMessage(Command.valueOf(op), data);
            } catch (UnknownHostException e) {
                // TODO
            }
        }

        Message.obtain(handler, HANDLER_TOAST, stuff).sendToTarget();
    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        String stuff = "Received some bytes! " + bytes.capacity() + " Filename: " + filename;
        Log.i(TAG, stuff);
        Message.obtain(handler, HANDLER_TOAST, stuff).sendToTarget();

        // saveFile(bytes.get)

        filename = null;
    }

    @Override
    public void onClose(int code, String reason, boolean remote) {
        String stuff = "Closed because " + reason + "(" + code + ")";
        Log.i(TAG, stuff);
        Message.obtain(handler, HANDLER_TOAST, stuff).sendToTarget();

    }

    @Override
    public void onError(Exception ex) {
        String stuff = "Error! " + ex.getMessage();
        Log.i(TAG, stuff);
        Message.obtain(handler, HANDLER_TOAST, stuff).sendToTarget();
    }

    private void handleMessage(Command command, String data) throws UnknownHostException {
        switch (command) {
        case IP:
            newHost = InetAddress.getByName(data);
            Message.obtain(handler, BaseDividerActivity.HANDLER_START_CLIENT, newHost).sendToTarget();
            close();
            break;
        case IP_PROPAGATE:
            Set<InetAddress> ips = new HashSet<InetAddress>();
            for (String ip : data.split(";")) {
                ips.add(InetAddress.getByName(ip));
            }
            break;
        case FILE:
            filename = data;
            break;
        default:
            break;
        }
    }

    private void saveFile(InputStream in) {

        if (context == null) {
            Message.obtain(handler, BaseDividerActivity.HANDLER_TOAST, "ERROR: CONTEXT NOT SET!").sendToTarget();
        }

        FileOutputStream fos = null;

        try {
            StringBuffer sb = new StringBuffer();
            int c;
            while ((c = in.read()) != -1) {
                char c2 = (char) c;
                if ('|' == c2) {
                    break;
                }
                sb.append(c2);
            }
            final String name = sb.toString();
            Log.d(TAG, "Saving file with name: " + name);

            fos = context.openFileOutput(name, Context.MODE_PRIVATE);
            Log.d(TAG, "server: copying files " + name);
            Utils.copyFile(in, fos);

            Message.obtain(handler, BaseDividerActivity.HANDLER_FILE, name).sendToTarget();
        } catch (IOException e) {

        } finally {
            Utils.closeQuietly(fos);
        }

    }

}